package com.example.rssreader.controller;

import com.example.rssreader.common.ApiResponse;
import com.example.rssreader.common.PageResponse;
import com.example.rssreader.dto.ArticleResponse;
import com.example.rssreader.service.ArticleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * 文章管理控制器
 * 提供文章的查询、阅读状态管理、搜索等功能
 * 
 * @author RSS Reader Team
 * @version 1.0.0
 * @since 2024-01-01
 */
@Slf4j
@RestController
@RequestMapping("/api/articles")
@RequiredArgsConstructor
@Validated
@Tag(name = "文章管理", description = "文章的查询、阅读状态管理、搜索等操作")
public class ArticleController {

    private final ArticleService articleService;

    /**
     * 分页查询文章列表
     * 
     * @param page   页码，从1开始，默认为1
     * @param size   每页大小，默认为20
     * @param feedId RSS源ID，可选参数
     * @param isRead 是否已读，可选参数
     * @return 文章分页列表
     */
    @GetMapping
    @Operation(summary = "分页查询文章列表", description = "获取文章列表，支持按RSS源和阅读状态过滤")
    public ApiResponse<PageResponse<ArticleResponse>> getArticles(
            @Parameter(description = "页码，从1开始") 
            @RequestParam(defaultValue = "1") @Min(value = 1, message = "页码必须大于0") Integer page,
            
            @Parameter(description = "每页大小，范围1-100") 
            @RequestParam(defaultValue = "20") @Min(value = 1, message = "每页大小必须大于0") Integer size,
            
            @Parameter(description = "RSS源ID，可选") 
            @RequestParam(required = false) Long feedId,
            
            @Parameter(description = "是否已读，可选") 
            @RequestParam(required = false) Boolean isRead) {
        
        log.debug("接收查询文章列表请求，页码: {}, 每页大小: {}, RSS源ID: {}, 是否已读: {}", 
                page, size, feedId, isRead);
        
        try {
            // 限制每页最大数量
            if (size > 100) {
                size = 100;
            }
            
            PageResponse<ArticleResponse> response = articleService.getArticles(page, size, feedId, isRead);
            return ApiResponse.success(response, "查询成功");
            
        } catch (Exception e) {
            log.error("查询文章列表失败: {}", e.getMessage(), e);
            return ApiResponse.error("查询文章列表失败: " + e.getMessage());
        }
    }

    /**
     * 根据ID获取文章详情
     * 
     * @param id 文章ID
     * @return 文章详细信息
     */
    @GetMapping("/{id}")
    @Operation(summary = "获取文章详情", description = "根据ID获取文章的详细信息，包含完整内容")
    public ApiResponse<ArticleResponse> getArticleById(
            @Parameter(description = "文章ID") 
            @PathVariable @NotNull(message = "文章ID不能为空") Long id) {
        
        log.debug("接收获取文章详情请求，ID: {}", id);
        
        try {
            ArticleResponse response = articleService.getArticleById(id);
            return ApiResponse.success(response, "查询成功");
            
        } catch (Exception e) {
            log.error("获取文章详情失败，ID: {}, 错误: {}", id, e.getMessage(), e);
            return ApiResponse.error("获取文章详情失败: " + e.getMessage());
        }
    }

    /**
     * 标记文章为已读
     * 
     * @param id 文章ID
     * @return 操作结果
     */
    @PostMapping("/{id}/read")
    @Operation(summary = "标记文章为已读", description = "将指定文章标记为已读状态")
    public ApiResponse<Void> markAsRead(
            @Parameter(description = "文章ID") 
            @PathVariable @NotNull(message = "文章ID不能为空") Long id) {
        
        log.debug("接收标记文章为已读请求，ID: {}", id);
        
        try {
            articleService.markAsRead(id);
            log.debug("文章标记为已读成功，ID: {}", id);
            return ApiResponse.success(null, "标记为已读成功");
            
        } catch (Exception e) {
            log.error("标记文章为已读失败，ID: {}, 错误: {}", id, e.getMessage(), e);
            return ApiResponse.error("标记文章为已读失败: " + e.getMessage());
        }
    }

    /**
     * 标记文章为未读
     * 
     * @param id 文章ID
     * @return 操作结果
     */
    @PostMapping("/{id}/unread")
    @Operation(summary = "标记文章为未读", description = "将指定文章标记为未读状态")
    public ApiResponse<Void> markAsUnread(
            @Parameter(description = "文章ID") 
            @PathVariable @NotNull(message = "文章ID不能为空") Long id) {
        
        log.debug("接收标记文章为未读请求，ID: {}", id);
        
        try {
            articleService.markAsUnread(id);
            log.debug("文章标记为未读成功，ID: {}", id);
            return ApiResponse.success(null, "标记为未读成功");
            
        } catch (Exception e) {
            log.error("标记文章为未读失败，ID: {}, 错误: {}", id, e.getMessage(), e);
            return ApiResponse.error("标记文章为未读失败: " + e.getMessage());
        }
    }

    /**
     * 批量标记文章为已读
     * 
     * @param articleIds 文章ID列表
     * @return 操作结果
     */
    @PostMapping("/batch-read")
    @Operation(summary = "批量标记文章为已读", description = "批量将多个文章标记为已读状态")
    public ApiResponse<Integer> batchMarkAsRead(
            @Parameter(description = "文章ID列表") 
            @RequestBody @NotEmpty(message = "文章ID列表不能为空") List<Long> articleIds) {
        
        log.info("接收批量标记文章为已读请求，文章数量: {}", articleIds.size());
        
        try {
            Integer updatedCount = articleService.batchMarkAsRead(articleIds);
            log.info("批量标记文章为已读成功，更新数量: {}", updatedCount);
            return ApiResponse.success(updatedCount, "批量标记为已读成功");
            
        } catch (Exception e) {
            log.error("批量标记文章为已读失败: {}", e.getMessage(), e);
            return ApiResponse.error("批量标记文章为已读失败: " + e.getMessage());
        }
    }

    /**
     * 标记RSS源下所有文章为已读
     * 
     * @param feedId RSS源ID
     * @return 操作结果
     */
    @PostMapping("/feeds/{feedId}/read-all")
    @Operation(summary = "标记RSS源下所有文章为已读", description = "将指定RSS源下的所有文章标记为已读状态")
    public ApiResponse<Integer> markFeedArticlesAsRead(
            @Parameter(description = "RSS源ID") 
            @PathVariable @NotNull(message = "RSS源ID不能为空") Long feedId) {
        
        log.info("接收标记RSS源文章为已读请求，RSS源ID: {}", feedId);
        
        try {
            Integer updatedCount = articleService.markFeedArticlesAsRead(feedId);
            log.info("标记RSS源文章为已读成功，RSS源ID: {}, 更新数量: {}", feedId, updatedCount);
            return ApiResponse.success(updatedCount, "标记RSS源文章为已读成功");
            
        } catch (Exception e) {
            log.error("标记RSS源文章为已读失败，RSS源ID: {}, 错误: {}", feedId, e.getMessage(), e);
            return ApiResponse.error("标记RSS源文章为已读失败: " + e.getMessage());
        }
    }

    /**
     * 搜索文章
     * 
     * @param keyword 搜索关键词
     * @param page    页码，从1开始，默认为1
     * @param size    每页大小，默认为20
     * @param feedId  RSS源ID，可选参数
     * @return 文章搜索结果
     */
    @GetMapping("/search")
    @Operation(summary = "搜索文章", description = "根据关键词搜索文章")
    public ApiResponse<PageResponse<ArticleResponse>> searchArticles(
            @Parameter(description = "搜索关键词") 
            @RequestParam @NotBlank(message = "搜索关键词不能为空") String keyword,
            
            @Parameter(description = "页码，从1开始") 
            @RequestParam(defaultValue = "1") @Min(value = 1, message = "页码必须大于0") Integer page,
            
            @Parameter(description = "每页大小，范围1-100") 
            @RequestParam(defaultValue = "20") @Min(value = 1, message = "每页大小必须大于0") Integer size,
            
            @Parameter(description = "RSS源ID，可选") 
            @RequestParam(required = false) Long feedId) {
        
        log.debug("接收搜索文章请求，关键词: {}, 页码: {}, 每页大小: {}, RSS源ID: {}", 
                keyword, page, size, feedId);
        
        try {
            // 限制每页最大数量
            if (size > 100) {
                size = 100;
            }
            
            PageResponse<ArticleResponse> response = articleService.searchArticles(keyword, page, size, feedId);
            return ApiResponse.success(response, "搜索成功");
            
        } catch (Exception e) {
            log.error("搜索文章失败，关键词: {}, 错误: {}", keyword, e.getMessage(), e);
            return ApiResponse.error("搜索文章失败: " + e.getMessage());
        }
    }

    /**
     * 获取未读文章数量
     * 
     * @param feedId RSS源ID，可选参数
     * @return 未读文章数量
     */
    @GetMapping("/unread-count")
    @Operation(summary = "获取未读文章数量", description = "获取未读文章的数量统计")
    public ApiResponse<Long> getUnreadCount(
            @Parameter(description = "RSS源ID，可选") 
            @RequestParam(required = false) Long feedId) {
        
        log.debug("接收获取未读文章数量请求，RSS源ID: {}", feedId);
        
        try {
            Long unreadCount = articleService.getUnreadCount(feedId);
            return ApiResponse.success(unreadCount, "查询成功");
            
        } catch (Exception e) {
            log.error("获取未读文章数量失败，RSS源ID: {}, 错误: {}", feedId, e.getMessage(), e);
            return ApiResponse.error("获取未读文章数量失败: " + e.getMessage());
        }
    }

    /**
     * 获取最新文章
     * 
     * @param limit 限制数量，默认10条
     * @return 最新文章列表
     */
    @GetMapping("/latest")
    @Operation(summary = "获取最新文章", description = "获取最新发布的文章列表")
    public ApiResponse<List<ArticleResponse>> getLatestArticles(
            @Parameter(description = "限制数量，默认10条") 
            @RequestParam(defaultValue = "10") @Min(value = 1, message = "限制数量必须大于0") Integer limit) {
        
        log.debug("接收获取最新文章请求，限制数量: {}", limit);
        
        try {
            // 限制最大数量
            if (limit > 50) {
                limit = 50;
            }
            
            List<ArticleResponse> articles = articleService.getLatestArticles(limit);
            return ApiResponse.success(articles, "查询成功");
            
        } catch (Exception e) {
            log.error("获取最新文章失败: {}", e.getMessage(), e);
            return ApiResponse.error("获取最新文章失败: " + e.getMessage());
        }
    }

    /**
     * 删除文章
     * 
     * @param id 文章ID
     * @return 删除结果
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除文章", description = "删除指定的文章")
    public ApiResponse<Void> deleteArticle(
            @Parameter(description = "文章ID") 
            @PathVariable @NotNull(message = "文章ID不能为空") Long id) {
        
        log.info("接收删除文章请求，ID: {}", id);
        
        try {
            articleService.deleteArticle(id);
            log.info("文章删除成功，ID: {}", id);
            return ApiResponse.success(null, "文章删除成功");
            
        } catch (Exception e) {
            log.error("删除文章失败，ID: {}, 错误: {}", id, e.getMessage(), e);
            return ApiResponse.error("删除文章失败: " + e.getMessage());
        }
    }

    /**
     * 批量删除文章
     * 
     * @param articleIds 文章ID列表
     * @return 删除结果
     */
    @DeleteMapping("/batch")
    @Operation(summary = "批量删除文章", description = "批量删除多个文章")
    public ApiResponse<Integer> batchDeleteArticles(
            @Parameter(description = "文章ID列表") 
            @RequestBody @NotEmpty(message = "文章ID列表不能为空") List<Long> articleIds) {
        
        log.info("接收批量删除文章请求，文章数量: {}", articleIds.size());
        
        try {
            Integer deletedCount = articleService.batchDeleteArticles(articleIds);
            log.info("批量删除文章成功，删除数量: {}", deletedCount);
            return ApiResponse.success(deletedCount, "批量删除文章成功");
            
        } catch (Exception e) {
            log.error("批量删除文章失败: {}", e.getMessage(), e);
            return ApiResponse.error("批量删除文章失败: " + e.getMessage());
        }
    }

    /**
     * 清理旧文章
     * 
     * @param daysAgo 天数，删除多少天前的文章
     * @return 清理结果
     */
    @DeleteMapping("/clean")
    @Operation(summary = "清理旧文章", description = "删除指定天数之前的文章")
    public ApiResponse<Integer> cleanOldArticles(
            @Parameter(description = "天数，删除多少天前的文章") 
            @RequestParam @Min(value = 1, message = "天数必须大于0") Integer daysAgo) {
        
        log.info("接收清理旧文章请求，删除{}天前的文章", daysAgo);
        
        try {
            Integer deletedCount = articleService.cleanOldArticles(daysAgo);
            log.info("清理旧文章成功，删除数量: {}", deletedCount);
            return ApiResponse.success(deletedCount, "清理旧文章成功");
            
        } catch (Exception e) {
            log.error("清理旧文章失败: {}", e.getMessage(), e);
            return ApiResponse.error("清理旧文章失败: " + e.getMessage());
        }
    }

    /**
     * 获取文章统计信息
     * 
     * @param feedId RSS源ID，可选参数
     * @return 文章统计信息
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取文章统计信息", description = "获取文章的统计数据")
    public ApiResponse<Object> getArticleStatistics(
            @Parameter(description = "RSS源ID，可选") 
            @RequestParam(required = false) Long feedId) {
        
        log.debug("接收获取文章统计信息请求，RSS源ID: {}", feedId);
        
        try {
            Object statistics = articleService.getArticleStatistics(feedId);
            return ApiResponse.success(statistics, "查询成功");
            
        } catch (Exception e) {
            log.error("获取文章统计信息失败，RSS源ID: {}, 错误: {}", feedId, e.getMessage(), e);
            return ApiResponse.error("获取文章统计信息失败: " + e.getMessage());
        }
    }

    /**
     * 标记所有文章为已读
     * 
     * @return 操作结果
     */
    @PostMapping("/read-all")
    @Operation(summary = "标记所有文章为已读", description = "将所有文章标记为已读状态")
    public ApiResponse<Integer> markAllAsRead() {
        
        log.info("接收标记所有文章为已读请求");
        
        try {
            Integer updatedCount = articleService.markAllAsRead();
            log.info("标记所有文章为已读成功，更新数量: {}", updatedCount);
            return ApiResponse.success(updatedCount, "标记所有文章为已读成功");
            
        } catch (Exception e) {
            log.error("标记所有文章为已读失败: {}", e.getMessage(), e);
            return ApiResponse.error("标记所有文章为已读失败: " + e.getMessage());
        }
    }
}